package com.atguigu.gulimall.product.service.impl;

import com.atguigu.gulimall.product.service.CategoryBrandRelationService;
import com.atguigu.gulimall.product.vo.web.Catelog2Vo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    //    三级分类 查出所欲分类以及子分类 以树形结构组装起来形成我们的列表
    @Override
    public List<CategoryEntity> listWithTree() {
        // 查询出所有分类
        List<CategoryEntity> entities = list(null);
        // 组装成父子树形结构

        // 找到所有的一级分类
        List<CategoryEntity> level1 = entities.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentCid().equals(0L);
        }).map((menu) -> {
            menu.setChildren(getChildrens(menu, entities));
            return menu;
        }).sorted((menu1, menu2) -> {

            // 小的在前面
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());

        }).collect(Collectors.toList());

        return level1;

    }

    // 1.检查当前删除的菜单是否被别的地方引用(删除)
    @Override
    public void removeMenusByIds(List<Long> catIds) {
        // TODO 检查以后删除菜单的时候这个菜单是否被引用
        // 逻辑删除
        boolean isflag = removeByIds(catIds);

    }

    // 根据三级分类来查询路径上的catId
    // [父/子/孙]
    // [2,25,225]
    @Override
    public Long[] findCatelogPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        List<Long> parentPath = findParentPath(catelogId, paths);

        Collections.reverse(parentPath);

        // 强制转为Long数组
        return parentPath.toArray(new Long[parentPath.size()]);
    }

    // 进行级联更新
    // TODO 修改我们categoryBrandRelationService里面的categoryName的名字
    @Transactional // 事务开启
    @Override
    public void updateCascade(CategoryEntity category) {
        // 修改本表
        this.updateById(category);

        // 修改了分类名字后 修改我们关联的表
        categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
    }

    // 1、查询出所有的一级分类
    @Override
    public List<CategoryEntity> getLevel1Categorys() {
        LambdaQueryWrapper<CategoryEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 得到一级分类
        lambdaQueryWrapper.eq(CategoryEntity::getParentCid,0);
        List<CategoryEntity> entities = list(lambdaQueryWrapper);
        return entities;
    }

    // 查询出相对应的二级分类的三级分类
    @Override
    public Map<String, List<Catelog2Vo>> getCatalogJson() {

        // 1.查询出所有1级分类  因为我们要有id
        List<CategoryEntity> level1Categorys = getLevel1Categorys();

        // 2.封装数据
        Map<String, List<Catelog2Vo>> parent_cid = level1Categorys.stream().collect(Collectors.toMap(k -> {
            return k.getCatId().toString();
        }, v -> {
            // 每一个一级分类 查到这个一级分类下面的所有二级分类
            LambdaQueryWrapper<CategoryEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(CategoryEntity::getParentCid, v.getCatId());
            List<CategoryEntity> entities = list(lambdaQueryWrapper);

            // 封装上面的结果
            List<Catelog2Vo> catelog2Vos = null;

            if (entities != null && entities.size() > 0) {
                // 得到我们二级分类的集合
                catelog2Vos = entities.stream().map((l2) -> {
                    Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, l2.getCatId().toString(), l2.getName());

                    // 1.找当前二级分类的三级分类封装为vo
                    LambdaQueryWrapper<CategoryEntity> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();

                    // item.getCatId() 就是二级分类的id
                    lambdaQueryWrapper1.eq(CategoryEntity::getParentCid,l2.getCatId());
                    // 2.得到这个二级分类下面的所有三级分类
                    List<CategoryEntity> list = list(lambdaQueryWrapper1);

                    // 如果没空也可以直接set进去
                    List<Catelog2Vo.Catalog3Vo> catalog3Vos = null;
                    // 非空的判断
                    if(list != null && list.size() > 0) {
                        // 3.对这个三级分类进行封装为我们需要的类型就可以了
                        catalog3Vos = list.stream().map((l3) -> {
                            Catelog2Vo.Catalog3Vo catalog3Vo = new Catelog2Vo.Catalog3Vo(l2.getCatId().toString(), l3.getCatId().toString(), l3.getName());
                            return catalog3Vo;
                        }).collect(Collectors.toList());
                    }

                    // 存入进去
                    catelog2Vo.setCatalog3List(catalog3Vos);

                    return catelog2Vo;
                }).collect(Collectors.toList());

            }
            // 要进行分装为2Vo


            return catelog2Vos;
        }));

        return parent_cid;
    }

    // 使用递归来实现找到父catId
    private List<Long> findParentPath(Long catelogId, List<Long> paths) {
        // 1.收集当前结点id
        paths.add(catelogId);
        CategoryEntity byId = getById(catelogId);
        if (byId.getParentCid() != 0) {
            findParentPath(byId.getParentCid(),paths);
        }
        return paths;
    }

    // 使用递归来字分类  后面是所有菜单
    private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {

        // 获取到一个子菜单 但是可能一个菜单还有子菜单 所以就要进行递归操作
        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
            return categoryEntity.getParentCid().equals(root.getCatId());
        }).map(categoryEntity -> {
            categoryEntity.setChildren(getChildrens(categoryEntity, all));
            return categoryEntity;
        }).sorted((menu1, menu2) -> {
            // 菜单的排序
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());
        return children;
    }

}